API GatewayとECS Fargateで「rm -rf 」を実行するAPIを作ってみた
世界一無駄なことをしたい
こんにちは、のんピ(@non____97)です。
以下記事で久しぶりにrm -rf /*
をしたら意外と楽しかったので、また試してみたいと思います。
今回は、「API GatewayとECS Fargateで"rm -rf /*"を実行するAPI」を作ってみます。恐らく世界一無駄なAPIだと思います。
参考までにこのシリーズの過去の記事は以下の通りです。
ちょっとはチャレンジ要素がないとつまらないので、作成するリソースは全てAWS CDKで定義しました。コードは以下をご覧ください。
構成図
構成図は以下の通りです。
ALBもしくはNLBにアクセスするようにしても良かったのですが、無性にAPI Gatewayを触ってみたくなったので、API GatewayをNLBの前段に置いています。
コードの確認
まず、コードの確認をします。
今回はコンテナ上で動かすので、恐らくrm -rf /*
したとしても、権限不足で盛大に怒られるのが目に見えています。
そこで、リクエストボディで指定した任意のディレクトリをrm -rf
するといったものを作ります。
今回はコンテナ上で手っ取り早く動かしたかったので、Expressを使ってWebサーバーを立ち上げます。
また、rm -rf
前後でどんなファイルが消されたか確認するために、rm -rf
前後にls -l
を実行します。
実際のコードは以下の通りです。
import * as express from "express"; import { spawnSync } from "child_process"; const app = express(); app.use(express.json()); app.use( express.urlencoded({ extended: true, }) ); app.get("/", async (req: express.Request, res: express.Response) => { console.log("get /"); res.status(200).json({ message: "rm -rf API" }); }); app.post("/", async (req: express.Request, res: express.Response) => { console.log("post /"); console.log(req.body); const dir = req.body.dir; // Run "ls -l" before "rm -rf const cmd_before_ls_l_dir = spawnSync(`ls -l ${dir}`, { shell: true }); console.log(`before ls -l ${dir} : ${cmd_before_ls_l_dir.stdout.toString()}`); // Run "rm -rf" const cmd_rm_rf_dir = spawnSync(`rm -rf ${dir}`, { shell: true }); console.log(`rm -rf ${dir} stdout: ${cmd_rm_rf_dir.stdout.toString()}`); console.log(`rm -rf ${dir} stderr: ${cmd_rm_rf_dir.stderr.toString()}`); // Run "ls -l" after "rm -rf const cmd_after_ls_l_dir = spawnSync(`ls -l ${dir}`, { shell: true }); console.log(`before ls -l ${dir} : ${cmd_after_ls_l_dir.stdout.toString()}`); res.status(200).json({ cmd_before_ls_l_dir: `${cmd_before_ls_l_dir.stdout.toString()}`, cmd_after_ls_l_dir: `${cmd_after_ls_l_dir.stdout.toString()}`, }); }); app.listen(80, () => { console.log("Example app listening on port 80!"); const cmd_pwd = spawnSync("pwd", { shell: true }).stdout.toString(); const cmd_ls_l = spawnSync("ls -l", { shell: true }).stdout.toString(); console.log(` pwd : ${cmd_pwd} ls -l : ${cmd_ls_l} `); });
API GatewayやECS Fargateを作成はAWS CDKで行います。
コンテナイメージをビルドしてECRにプッシュする際はcdk-ecr-deployment
を使用しました。
API GatewayとNLBを連携させるにあたってはVPCリンクを使用します。VPCリンクの詳細な説明は以下記事をご覧ください。
実際のコードは以下の通りです。
import { Aws, Stack, StackProps, aws_ec2 as ec2, aws_ecr as ecr, aws_ecr_assets as ecr_assets, aws_ecs as ecs, aws_ecs_patterns as ecs_patterns, aws_apigateway as apigateway, } from "aws-cdk-lib"; import { Construct } from "constructs"; import * as path from "path"; import * as ecr_deploy from "cdk-ecr-deployment"; export class ApiStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); // VPC const vpc = new ec2.Vpc(this, "Vpc", { cidr: "10.0.0.0/24", enableDnsHostnames: true, enableDnsSupport: true, natGateways: 1, maxAzs: 2, subnetConfiguration: [ { name: "Public", subnetType: ec2.SubnetType.PUBLIC, cidrMask: 27 }, { name: "Private", subnetType: ec2.SubnetType.PRIVATE_WITH_NAT, cidrMask: 27, }, ], }); // ECR Repository const repository = new ecr.Repository(this, "Repository", { imageScanOnPush: true, }); // Image const image = new ecr_assets.DockerImageAsset(this, "image", { directory: path.join(__dirname, "../src/images/rm-rf-root"), }); // Deploy Image new ecr_deploy.ECRDeployment(this, "DeployImage", { src: new ecr_deploy.DockerImageName(image.imageUri), dest: new ecr_deploy.DockerImageName( `${Aws.ACCOUNT_ID}.dkr.ecr.${Aws.REGION}.amazonaws.com/${repository.repositoryName}` ), }); // ECS Cluster const ecsCluster = new ecs.Cluster(this, "EcsCluster", { vpc, containerInsights: true, }); // ECS Task Definition const taskDefinition = new ecs.FargateTaskDefinition( this, "TaskDefinition" ); taskDefinition .addContainer("rm-rf-rootContainer", { image: ecs.ContainerImage.fromEcrRepository(repository, "latest"), memoryLimitMiB: 256, logging: ecs.LogDriver.awsLogs({ streamPrefix: repository.repositoryName, }), }) .addPortMappings({ protocol: ecs.Protocol.TCP, containerPort: 80, hostPort: 80, }); // NLB const loadBalancedFargateService = new ecs_patterns.NetworkLoadBalancedFargateService( this, "LoadBalancedFargateService", { assignPublicIp: false, cluster: ecsCluster, taskSubnets: vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_NAT, }), memoryLimitMiB: 1024, cpu: 512, desiredCount: 2, taskDefinition: taskDefinition, publicLoadBalancer: true, } ); loadBalancedFargateService.service.connections.allowFrom( ec2.Peer.ipv4(vpc.vpcCidrBlock), ec2.Port.tcp(80) ); // Auto Scaling Settings const scalableTarget = loadBalancedFargateService.service.autoScaleTaskCount({ minCapacity: 2, maxCapacity: 10, }); scalableTarget.scaleOnCpuUtilization("CpuScaling", { targetUtilizationPercent: 50, }); scalableTarget.scaleOnMemoryUtilization("MemoryScaling", { targetUtilizationPercent: 50, }); // VPC Link const link = new apigateway.VpcLink(this, "link", { targets: [loadBalancedFargateService.loadBalancer], }); const getIntegration = new apigateway.Integration({ type: apigateway.IntegrationType.HTTP_PROXY, integrationHttpMethod: "GET", options: { connectionType: apigateway.ConnectionType.VPC_LINK, vpcLink: link, }, }); const postIntegration = new apigateway.Integration({ type: apigateway.IntegrationType.HTTP_PROXY, integrationHttpMethod: "POST", options: { connectionType: apigateway.ConnectionType.VPC_LINK, vpcLink: link, }, }); // API Gateway const api = new apigateway.RestApi(this, "Api"); api.root.addMethod("GET", getIntegration); api.root.addMethod("POST", postIntegration); } }
やってみた
npx cdk deploy
でAWS CDKで定義したリソースをデプロイします。
しばらくすると、ECSクラスターや、NLB、API Gatewayなどが作成されていることを確認できました。
ECSクラスター
NLB
API Gateway
また、CloudWatch Logsを確認すると、正しくWebサーバーが立ち上がっていることを確認できます。
> [email protected] start /usr/src/app > ts-node src/index.ts Example app listening on port 80! pwd : /usr/src/app ls -l : total 48 -rw-r--r-- 1 root root 234 Mar 23 09:07 Dockerfile drwxr-xr-x 1 root root 4096 Mar 23 09:08 node_modules -rw-r--r-- 1 root root 22474 Mar 23 09:08 package-lock.json -rw-r--r-- 1 root root 380 Mar 23 09:08 package.json drwxr-xr-x 2 root root 4096 Mar 23 09:07 rm-test drwxr-xr-x 2 root root 4096 Mar 23 09:07 src -rw-r--r-- 1 root root 650 Mar 23 09:07 tsconfig.json
それでは、まずGETでリクエストをしてみます。
> curl https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ {"message":"rm -rf API"}
「俺は危険なAPIだぞ」というアピールをされました。
続いて、POSTでリクエストします。手始めにということで、リクエストボディには{"dir": "./Dockerfile"}
を渡します。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "./Dockerfile"}' {"cmd_before_ls_l_dir":"-rw-r--r-- 1 root root 234 Mar 23 07:23 ./Dockerfile\n","cmd_after_ls_l_dir":""}
"cmd_after_ls_l_dir":""
となっていることからrm -rf
で./Dockerfile
が削除されていることが確認できます。
CloudWatch Logsからも同様の結果を確認できました。
post / { dir: './Dockerfile' } before ls -l ./Dockerfile : -rw-r--r-- 1 root root 234 Mar 23 07:23 ./Dockerfile rm -rf ./Dockerfile stdout: rm -rf ./Dockerfile stderr: before ls -l ./Dockerfile :
もう一度リクエストボディを{"dir": "./Dockerfile"}
にしてPOSTします。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "./Dockerfile"}' {"cmd_before_ls_l_dir":"","cmd_after_ls_l_dir":""}⏎
既に./Dockerfile
が削除されて存在しないので、cmd_before_ls_l_dir":""
となっています。
次にリクエストボディを{"dir": "/"}
としてPOSTします。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "/"}' {"cmd_before_ls_l_dir":"total 72\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 bin\ndrwxr-xr-x 2 root root 4096 Jul 10 2020 boot\ndrwxr-xr-x 5 root root 340 Mar 23 07:26 dev\ndrwxr-xr-x 1 root root 4096 Mar 23 07:26 etc\ndrwxr-xr-x 1 root root 4096 Mar 17 13:01 home\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 lib\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 lib64\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 media\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 mnt\ndrwxr-xr-x 1 root root 4096 Mar 18 21:54 opt\ndr-xr-xr-x 96 root root 0 Mar 23 07:26 proc\ndrwx------ 1 root root 4096 Mar 23 07:23 root\ndrwxr-xr-x 3 root root 4096 Mar 16 00:00 run\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 sbin\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 srv\ndr-xr-xr-x 13 root root 0 Mar 23 07:26 sys\ndrwxrwxrwt 1 root root 4096 Mar 23 07:23 tmp\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 usr\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 var\n","cmd_after_ls_l_dir":"total 72\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 bin\ndrwxr-xr-x 2 root root 4096 Jul 10 2020 boot\ndrwxr-xr-x 5 root root 340 Mar 23 07:26 dev\ndrwxr-xr-x 1 root root 4096 Mar 23 07:26 etc\ndrwxr-xr-x 1 root root 4096 Mar 17 13:01 home\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 lib\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 lib64\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 media\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 mnt\ndrwxr-xr-x 1 root root 4096 Mar 18 21:54 opt\ndr-xr-xr-x 97 root root 0 Mar 23 07:26 proc\ndrwx------ 1 root root 4096 Mar 23 07:23 root\ndrwxr-xr-x 3 root root 4096 Mar 16 00:00 run\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 sbin\ndrwxr-xr-x 2 root root 4096 Mar 16 00:00 srv\ndr-xr-xr-x 13 root root 0 Mar 23 07:29 sys\ndrwxrwxrwt 1 root root 4096 Mar 23 07:23 tmp\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 usr\ndrwxr-xr-x 1 root root 4096 Mar 16 00:00 var\n"}
これでは訳がわからないのでCloudWatch Logsを確認します。rm -rf /
をしようとしたけど--no-preserve-root
オプションがないため、怒られていますね。
post / { dir: '/' } before ls -l / : total 72 drwxr-xr-x 2 root root 4096 Mar 16 00:00 bin drwxr-xr-x 2 root root 4096 Jul 10 2020 boot drwxr-xr-x 5 root root 340 Mar 23 07:26 dev drwxr-xr-x 1 root root 4096 Mar 23 07:26 etc drwxr-xr-x 1 root root 4096 Mar 17 13:01 home drwxr-xr-x 1 root root 4096 Mar 16 00:00 lib drwxr-xr-x 2 root root 4096 Mar 16 00:00 lib64 drwxr-xr-x 2 root root 4096 Mar 16 00:00 media drwxr-xr-x 2 root root 4096 Mar 16 00:00 mnt drwxr-xr-x 1 root root 4096 Mar 18 21:54 opt dr-xr-xr-x 96 root root 0 Mar 23 07:26 proc drwx------ 1 root root 4096 Mar 23 07:23 root drwxr-xr-x 3 root root 4096 Mar 16 00:00 run drwxr-xr-x 2 root root 4096 Mar 16 00:00 sbin drwxr-xr-x 2 root root 4096 Mar 16 00:00 srv dr-xr-xr-x 13 root root 0 Mar 23 07:26 sys drwxrwxrwt 1 root root 4096 Mar 23 07:23 tmp drwxr-xr-x 1 root root 4096 Mar 16 00:00 usr drwxr-xr-x 1 root root 4096 Mar 16 00:00 var rm -rf / stdout: rm -rf / stderr: rm: it is dangerous to operate recursively on '/' rm: use --no-preserve-root to override this failsafe before ls -l / : total 72 drwxr-xr-x 2 root root 4096 Mar 16 00:00 bin drwxr-xr-x 2 root root 4096 Jul 10 2020 boot drwxr-xr-x 5 root root 340 Mar 23 07:26 dev drwxr-xr-x 1 root root 4096 Mar 23 07:26 etc drwxr-xr-x 1 root root 4096 Mar 17 13:01 home drwxr-xr-x 1 root root 4096 Mar 16 00:00 lib drwxr-xr-x 2 root root 4096 Mar 16 00:00 lib64 drwxr-xr-x 2 root root 4096 Mar 16 00:00 media drwxr-xr-x 2 root root 4096 Mar 16 00:00 mnt drwxr-xr-x 1 root root 4096 Mar 18 21:54 opt dr-xr-xr-x 97 root root 0 Mar 23 07:26 proc drwx------ 1 root root 4096 Mar 23 07:23 root drwxr-xr-x 3 root root 4096 Mar 16 00:00 run drwxr-xr-x 2 root root 4096 Mar 16 00:00 sbin drwxr-xr-x 2 root root 4096 Mar 16 00:00 srv dr-xr-xr-x 13 root root 0 Mar 23 07:29 sys drwxrwxrwt 1 root root 4096 Mar 23 07:23 tmp drwxr-xr-x 1 root root 4096 Mar 16 00:00 usr drwxr-xr-x 1 root root 4096 Mar 16 00:00 var
次にリクエストボディを{"dir": "/*"}
としてPOSTします。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "/*"}' {"message": "Endpoint request timed out"}
タイムアウトしてしまいましたね。
CloudWatch Logsを確認します。/sys/kernel/
などを削除しようとして怒られていますね。当然です。
. . . rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/validate': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/free_calls': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/min_partial': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/poison': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/red_zone': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/slabs': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/destroy_by_rcu': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/sanity_checks': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/align': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/aliases': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/store_user': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/trace': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/reclaim_account': Read-only file system rm: cannot remove '/sys/kernel/slab/:A-0000200/cgroup/vm_area_struct(800:postfix.service)/order': Read-only file system
最後に、リクエストボディを{"dir": "./*"}
としてPOSTします。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "./*"}' {"cmd_before_ls_l_dir":"-rw-r--r-- 1 root root 234 Mar 23 09:07 ./Dockerfile\n-rw-r--r-- 1 root root 22474 Mar 23 09:08 ./package-lock.json\n-rw-r--r-- 1 root root 380 Mar 23 09:08 ./package.json\n-rw-r--r-- 1 root root 650 Mar 23 09:07 ./tsconfig.json\n\n./node_modules:\ntotal 248\ndrwxr-xr-x 4 root root 4096 Mar 23 09:08 @cspotcode\ndrwxr-xr-x 6 root root 4096 Mar 23 09:08 @tsconfig\ndrwxr-xr-x 11 root root 4096 Mar 23 09:08 @types\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 accepts\ndrwxr-xr-x 4 root root 4096 Mar 23 09:08 acorn\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 acorn-walk\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 arg\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 array-flatten\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 body-parser\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 bytes\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 content-disposition\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 content-type\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 cookie\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 cookie-signature\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 create-require\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 debug\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 depd\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 destroy\ndrwxr-xr-x 4 root root 4096 Mar 23 09:08 diff\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 ee-first\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 encodeurl\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 escape-html\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 etag\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 express\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 finalhandler\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 forwarded\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 fresh\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 http-errors\ndrwxr-xr-x 4 root root 4096 Mar 23 09:08 iconv-lite\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 inherits\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 ipaddr.js\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 make-error\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 media-typer\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 merge-descriptors\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 methods\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 mime\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 mime-db\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 mime-types\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 ms\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 negotiator\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 on-finished\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 parseurl\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 path-to-regexp\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 proxy-addr\ndrwxr-xr-x 6 root root 4096 Mar 23 09:08 qs\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 range-parser\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 raw-body\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 safe-buffer\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 safer-buffer\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 send\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 serve-static\ndrwxr-xr-x 3 root root 4096 Mar 23 09:08 setprototypeof\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 statuses\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 toidentifier\ndrwxr-xr-x 11 root root 4096 Mar 23 09:08 ts-node\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 type-is\ndrwxr-xr-x 5 root root 4096 Mar 23 09:08 typescript\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 unpipe\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 utils-merge\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 v8-compile-cache-lib\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 vary\ndrwxr-xr-x 2 root root 4096 Mar 23 09:08 yn\n\n./rm-test:\ntotal 0\n-rw-r--r-- 1 root root 0 Mar 23 09:07 rm-file\n\n./src:\ntotal 4\n-rw-r--r-- 1 root root 1567 Mar 23 09:07 index.ts\n","cmd_after_ls_l_dir":""}
これも訳がわからないのでCloudWatch Logsを確認します。どうやらカレントディレクトリ配下を全て削除できているようです。
post / { dir: './*' } before ls -l ./* : -rw-r--r-- 1 root root 234 Mar 23 09:07 ./Dockerfile -rw-r--r-- 1 root root 22474 Mar 23 09:08 ./package-lock.json -rw-r--r-- 1 root root 380 Mar 23 09:08 ./package.json -rw-r--r-- 1 root root 650 Mar 23 09:07 ./tsconfig.json ./node_modules: total 248 drwxr-xr-x 4 root root 4096 Mar 23 09:08 @cspotcode drwxr-xr-x 6 root root 4096 Mar 23 09:08 @tsconfig drwxr-xr-x 11 root root 4096 Mar 23 09:08 @types drwxr-xr-x 2 root root 4096 Mar 23 09:08 accepts drwxr-xr-x 4 root root 4096 Mar 23 09:08 acorn drwxr-xr-x 3 root root 4096 Mar 23 09:08 acorn-walk drwxr-xr-x 2 root root 4096 Mar 23 09:08 arg drwxr-xr-x 2 root root 4096 Mar 23 09:08 array-flatten drwxr-xr-x 3 root root 4096 Mar 23 09:08 body-parser drwxr-xr-x 2 root root 4096 Mar 23 09:08 bytes drwxr-xr-x 2 root root 4096 Mar 23 09:08 content-disposition drwxr-xr-x 2 root root 4096 Mar 23 09:08 content-type drwxr-xr-x 2 root root 4096 Mar 23 09:08 cookie drwxr-xr-x 2 root root 4096 Mar 23 09:08 cookie-signature drwxr-xr-x 2 root root 4096 Mar 23 09:08 create-require drwxr-xr-x 3 root root 4096 Mar 23 09:08 debug drwxr-xr-x 3 root root 4096 Mar 23 09:08 depd drwxr-xr-x 2 root root 4096 Mar 23 09:08 destroy drwxr-xr-x 4 root root 4096 Mar 23 09:08 diff drwxr-xr-x 2 root root 4096 Mar 23 09:08 ee-first drwxr-xr-x 2 root root 4096 Mar 23 09:08 encodeurl drwxr-xr-x 2 root root 4096 Mar 23 09:08 escape-html drwxr-xr-x 2 root root 4096 Mar 23 09:08 etag drwxr-xr-x 3 root root 4096 Mar 23 09:08 express drwxr-xr-x 2 root root 4096 Mar 23 09:08 finalhandler drwxr-xr-x 2 root root 4096 Mar 23 09:08 forwarded drwxr-xr-x 2 root root 4096 Mar 23 09:08 fresh drwxr-xr-x 2 root root 4096 Mar 23 09:08 http-errors drwxr-xr-x 4 root root 4096 Mar 23 09:08 iconv-lite drwxr-xr-x 2 root root 4096 Mar 23 09:08 inherits drwxr-xr-x 3 root root 4096 Mar 23 09:08 ipaddr.js drwxr-xr-x 3 root root 4096 Mar 23 09:08 make-error drwxr-xr-x 2 root root 4096 Mar 23 09:08 media-typer drwxr-xr-x 2 root root 4096 Mar 23 09:08 merge-descriptors drwxr-xr-x 2 root root 4096 Mar 23 09:08 methods drwxr-xr-x 3 root root 4096 Mar 23 09:08 mime drwxr-xr-x 2 root root 4096 Mar 23 09:08 mime-db drwxr-xr-x 2 root root 4096 Mar 23 09:08 mime-types drwxr-xr-x 2 root root 4096 Mar 23 09:08 ms drwxr-xr-x 3 root root 4096 Mar 23 09:08 negotiator drwxr-xr-x 2 root root 4096 Mar 23 09:08 on-finished drwxr-xr-x 2 root root 4096 Mar 23 09:08 parseurl drwxr-xr-x 2 root root 4096 Mar 23 09:08 path-to-regexp drwxr-xr-x 2 root root 4096 Mar 23 09:08 proxy-addr drwxr-xr-x 6 root root 4096 Mar 23 09:08 qs drwxr-xr-x 2 root root 4096 Mar 23 09:08 range-parser drwxr-xr-x 2 root root 4096 Mar 23 09:08 raw-body drwxr-xr-x 2 root root 4096 Mar 23 09:08 safe-buffer drwxr-xr-x 2 root root 4096 Mar 23 09:08 safer-buffer drwxr-xr-x 3 root root 4096 Mar 23 09:08 send drwxr-xr-x 2 root root 4096 Mar 23 09:08 serve-static drwxr-xr-x 3 root root 4096 Mar 23 09:08 setprototypeof drwxr-xr-x 2 root root 4096 Mar 23 09:08 statuses drwxr-xr-x 2 root root 4096 Mar 23 09:08 toidentifier drwxr-xr-x 11 root root 4096 Mar 23 09:08 ts-node drwxr-xr-x 2 root root 4096 Mar 23 09:08 type-is drwxr-xr-x 5 root root 4096 Mar 23 09:08 typescript drwxr-xr-x 2 root root 4096 Mar 23 09:08 unpipe drwxr-xr-x 2 root root 4096 Mar 23 09:08 utils-merge drwxr-xr-x 2 root root 4096 Mar 23 09:08 v8-compile-cache-lib drwxr-xr-x 2 root root 4096 Mar 23 09:08 vary drwxr-xr-x 2 root root 4096 Mar 23 09:08 yn ./rm-test: total 0 -rw-r--r-- 1 root root 0 Mar 23 09:07 rm-file ./src: total 4 -rw-r--r-- 1 root root 1567 Mar 23 09:07 index.ts rm -rf ./* stdout: rm -rf ./* stderr: before ls -l ./* :
もう一度リクエストボディを{"dir": "./*"}
としてPOSTします。
> curl -H "Content-Type: application/json" -X POST https://nlhss0riw5.execute-api.us-east-1.amazonaws.com/prod/ -d '{"dir": "./*"}' {"cmd_before_ls_l_dir":"","cmd_after_ls_l_dir":""}
カレントディレクトリは空のはずなのに元気にレスポンスを返してくれました。恐らくメモリ上に残った力で対応してくれているのでしょう。健気ですね。
CLP やってみるを体現した
API GatewayとECS Fargateで"rm -rf /*"を実行するAPIを作ってみました。
久しぶりにECSやAPI Gatewayを使ってみて今回も非常に有意義な時間を過ごせました。
この記事は誰の役にも立たないかもしれませんが、誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!